package com.mojian.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mojian.common.Result;
import com.mojian.config.AlipayConfig;
import com.mojian.entity.MemberOrder;
import com.mojian.entity.MemberPlan;
import com.mojian.entity.MemberUser;
import com.mojian.mapper.MemberOrderMapper;
import com.mojian.mapper.MemberPlanMapper;
import com.mojian.mapper.MemberUserMapper;
import com.mojian.model.vo.MemberOrderVO;
import com.mojian.model.vo.MemberPlanVO;
import com.mojian.model.vo.MemberUserVO;
import com.mojian.service.MemberService;
import cn.dev33.satoken.stp.StpUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * 会员服务实现
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class MemberServiceImpl implements MemberService {

    private final AlipayClient alipayClient;
    private final AlipayConfig alipayConfig;
    private final MemberOrderMapper memberOrderMapper;
    private final MemberUserMapper memberUserMapper;
    private final MemberPlanMapper memberPlanMapper;
    private final JdbcTemplate jdbcTemplate;

    /**
     * 生成订单号
     * 格式：年月日时分秒 + 4位随机数
     */
    private String generateOrderNo() {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        String timeStr = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        
        // 生成4位随机数
        Random random = new Random();
        int randomNum = random.nextInt(10000);
        String randomStr = String.format("%04d", randomNum);
        
        return "VIP" + timeStr + randomStr;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<MemberOrderVO> createMemberOrder(MemberOrderVO orderVO) {
        log.info("创建会员订单: {}", orderVO);
        
        // 验证套餐是否存在
        MemberPlan memberPlan = memberPlanMapper.selectById(orderVO.getPlanId());
        if (memberPlan == null) {
            return Result.error("套餐不存在");
        }
        
        // 获取用户ID
        Long userId = StpUtil.getLoginIdAsLong();
        
        // 生成订单号
        String orderNo = generateOrderNo();
        log.info("生成订单号: {}", orderNo);
        
        try {
            // 创建订单记录
            MemberOrder order = MemberOrder.builder()
                    .orderNo(orderNo)
                    .userId(userId)
                    .planId(orderVO.getPlanId())
                    .days(memberPlan.getDays())
                    .paymentMethod(orderVO.getPaymentMethod())
                    .amount(memberPlan.getPrice())
                    .status("PENDING")
                    .createTime(LocalDateTime.now())
                    .updateTime(LocalDateTime.now())
                    .build();
                    
            memberOrderMapper.insert(order);
            log.info("会员订单已保存到数据库: {}", order);
            
            // 如果是支付宝支付，调用支付宝接口生成支付二维码
            if ("alipay".equals(orderVO.getPaymentMethod())) {
                // 创建预下单请求
                AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
                request.setNotifyUrl(alipayConfig.getNotifyUrl());
                
                // 构建业务参数
                JSONObject bizContent = new JSONObject();
                bizContent.put("out_trade_no", orderNo);
                bizContent.put("total_amount", memberPlan.getPrice().toString());
                bizContent.put("subject", memberPlan.getName());
                bizContent.put("body", "会员订阅: " + memberPlan.getName());
                // 设置超时时间
                bizContent.put("timeout_express", "15m");
                
                request.setBizContent(bizContent.toString());
                log.info("调用支付宝预下单接口，请求参数: {}", bizContent);
                
                // 记录开始时间
                long startTime = System.currentTimeMillis();
                
                try {
                    AlipayTradePrecreateResponse response = alipayClient.execute(request);
                    
                    long endTime = System.currentTimeMillis();
                    log.info("支付宝预下单接口调用耗时: {}ms", (endTime - startTime));
                    log.info("支付宝预下单接口响应: {}", response.getBody());
                    
                    if (response.isSuccess()) {
                        // 获取支付宝返回的二维码字符串
                        String qrCode = response.getQrCode();
                        log.info("支付宝返回二维码内容: {}", qrCode);
                        
                        // 将结果返回给前端
                        orderVO.setOrderNo(orderNo);
                        orderVO.setStatus("PENDING");
                        
                        // 为了保证二维码能正确显示，我们生成一个图片URL
                        String qrCodeUrl = "https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=" + qrCode;
                        log.info("生成的二维码图片URL: {}", qrCodeUrl);
                        orderVO.setQrCodeUrl(qrCodeUrl);  // 使用二维码图片URL
                        
                        orderVO.setAmount(memberPlan.getPrice());
                        orderVO.setDays(memberPlan.getDays());
                        return Result.success(orderVO);
                    } else {
                        log.error("创建支付宝订单失败: code={}, msg={}, sub_code={}, sub_msg={}",
                                response.getCode(), response.getMsg(), response.getSubCode(), response.getSubMsg());
                        return Result.error("创建订单失败: " + response.getSubMsg());
                    }
                } catch (Exception e) {
                    String errorMsg = "创建订单失败";
                    if (e instanceof java.net.SocketTimeoutException ||
                        (e.getCause() != null && e.getCause() instanceof java.net.SocketTimeoutException)) {
                        errorMsg = "支付宝接口请求超时，请稍后再试";
                        log.error("支付宝接口请求超时: {}", e.getMessage());
                    } else {
                        log.error("创建支付宝订单异常", e);
                    }
                    return Result.error(errorMsg);
                }
            } else {
                // 微信支付或其他支付方式
                // 暂时返回模拟数据
                orderVO.setOrderNo(orderNo);
                orderVO.setStatus("PENDING");
                orderVO.setQrCodeUrl("https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=TestOrder:" + orderNo);
                orderVO.setAmount(memberPlan.getPrice());
                orderVO.setDays(memberPlan.getDays());
                return Result.success(orderVO);
            }
        } catch (Exception e) {
            log.error("创建会员订单异常", e);
            return Result.error("创建订单失败: " + e.getMessage());
        }
    }

    @Override
    public Result<MemberOrderVO> checkOrderStatus(String orderNo) {
        log.info("查询会员订单状态: {}", orderNo);
        
        // 查询订单信息
        LambdaQueryWrapper<MemberOrder> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(MemberOrder::getOrderNo, orderNo);
        MemberOrder order = memberOrderMapper.selectOne(queryWrapper);
        
        if (order == null) {
            return Result.error("订单不存在");
        }
        
        // 如果订单已支付成功，直接返回
        if ("SUCCESS".equals(order.getStatus())) {
            MemberOrderVO orderVO = new MemberOrderVO();
            orderVO.setOrderNo(order.getOrderNo());
            orderVO.setStatus(order.getStatus());
            orderVO.setAmount(order.getAmount());
            orderVO.setPlanId(order.getPlanId());
            orderVO.setDays(order.getDays());
            
            // 重建会员文章访问权限
            rebuildAllMemberArticleAccess();
            
            return Result.success(orderVO);
        }
        
        // 如果是支付宝支付，调用支付宝接口查询订单状态
        if ("alipay".equals(order.getPaymentMethod())) {
            try {
                AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
                JSONObject bizContent = new JSONObject();
                bizContent.put("out_trade_no", orderNo);
                request.setBizContent(bizContent.toString());
                
                log.info("调用支付宝查询订单接口，订单号: {}", orderNo);
                AlipayTradeQueryResponse response = alipayClient.execute(request);
                log.info("支付宝查询订单接口响应: {}", response.getBody());
                
                if (response.isSuccess()) {
                    // 交易状态: WAIT_BUYER_PAY（交易创建，等待买家付款）、TRADE_CLOSED（未付款交易超时关闭）、TRADE_SUCCESS（交易支付成功）、TRADE_FINISHED（交易结束，不可退款）
                    String tradeStatus = response.getTradeStatus();
                    
                    MemberOrderVO orderVO = new MemberOrderVO();
                    orderVO.setOrderNo(order.getOrderNo());
                    orderVO.setPlanId(order.getPlanId());
                    orderVO.setAmount(order.getAmount());
                    orderVO.setDays(order.getDays());
                    
                    if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                        // 支付成功，更新订单状态
                        order.setStatus("SUCCESS");
                        order.setTradeNo(response.getTradeNo());
                        order.setPayTime(LocalDateTime.now());
                        order.setUpdateTime(LocalDateTime.now());
                        memberOrderMapper.updateById(order);
                        
                        orderVO.setStatus("SUCCESS");
                        
                        // 激活会员
                        boolean activated = activateMembership(order.getUserId(), order.getDays());
                        if (activated) {
                            log.info("用户[{}]会员已激活，有效期{}天", order.getUserId(), order.getDays());
                        } else {
                            log.error("用户[{}]会员激活失败", order.getUserId());
                        }
                        
                        log.info("订单支付成功，已更新状态: {}", order);
                    } else if ("WAIT_BUYER_PAY".equals(tradeStatus)) {
                        orderVO.setStatus("PENDING");
                    } else {
                        orderVO.setStatus("FAILED");
                        
                        // 更新订单状态为失败
                        order.setStatus("FAILED");
                        order.setUpdateTime(LocalDateTime.now());
                        memberOrderMapper.updateById(order);
                    }
                    
                    return Result.success(orderVO);
                } else {
                    log.error("查询支付宝订单失败: code={}, msg={}, sub_code={}, sub_msg={}",
                            response.getCode(), response.getMsg(), response.getSubCode(), response.getSubMsg());
                    
                    MemberOrderVO orderVO = new MemberOrderVO();
                    orderVO.setOrderNo(order.getOrderNo());
                    orderVO.setStatus(order.getStatus());
                    orderVO.setAmount(order.getAmount());
                    orderVO.setPlanId(order.getPlanId());
                    return Result.success(orderVO);
                }
            } catch (Exception e) {
                log.error("查询支付宝订单异常", e);
                
                MemberOrderVO orderVO = new MemberOrderVO();
                orderVO.setOrderNo(order.getOrderNo());
                orderVO.setStatus(order.getStatus());
                orderVO.setAmount(order.getAmount());
                orderVO.setPlanId(order.getPlanId());
                return Result.success(orderVO);
            }
        } else {
            // 其他支付方式，返回数据库中的状态
            MemberOrderVO orderVO = new MemberOrderVO();
            orderVO.setOrderNo(order.getOrderNo());
            orderVO.setStatus(order.getStatus());
            orderVO.setAmount(order.getAmount());
            orderVO.setPlanId(order.getPlanId());
            return Result.success(orderVO);
        }
    }

    @Override
    public String handleAlipayNotify(Map<String, String> params) {
        log.info("处理支付宝异步通知: {}", params);
        return "success";
    }

    @Override
    public Result<List<MemberPlanVO>> getMemberPlans() {
        log.info("获取会员套餐列表");
        // 暂时返回模拟数据
        List<MemberPlanVO> plans = new ArrayList<>();
        plans.add(MemberPlanVO.builder().id(1).name("月度会员").price(new BigDecimal("30.00")).days(30).unit("月").build());
        plans.add(MemberPlanVO.builder().id(2).name("季度会员").price(new BigDecimal("78.00")).originalPrice(new BigDecimal("90.00")).days(90).unit("季").discount(8.7).build());
        plans.add(MemberPlanVO.builder().id(3).name("年度会员").price(new BigDecimal("258.00")).originalPrice(new BigDecimal("360.00")).days(365).unit("年").discount(7.2).build());
        return Result.success(plans);
    }

    @Override
    public Result<MemberUserVO> getCurrentMemberInfo() {
        log.info("获取当前用户会员信息");
        // 暂时返回模拟数据
        MemberUserVO userVO = MemberUserVO.builder()
                .userId(StpUtil.isLogin() ? Long.parseLong(StpUtil.getLoginIdAsString()) : 0L)
                .isMember(false)
                .level(0)
                .remainingDays(0)
                .build();
        return Result.success(userVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean activateMembership(Long userId, Integer days) {
        log.info("激活用户[{}]的会员，有效期{}天", userId, days);
        
        try {
            // 查询用户当前会员信息
            LambdaQueryWrapper<MemberUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(MemberUser::getUserId, userId);
            MemberUser memberUser = memberUserMapper.selectOne(queryWrapper);
            
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime expireTime;
            
            if (memberUser == null) {
                // 新用户，创建会员信息
                memberUser = MemberUser.builder()
                        .userId(userId)
                        .level(1)  // 默认等级为1
                        .startTime(now)
                        .expireTime(now.plusDays(days))
                        .createTime(now)
                        .updateTime(now)
                        .build();
                memberUserMapper.insert(memberUser);
                log.info("新用户会员信息创建成功: {}", memberUser);
            } else {
                // 更新已有用户的会员信息
                if (memberUser.getExpireTime() != null && memberUser.getExpireTime().isAfter(now)) {
                    // 如果会员未过期，在现有到期时间的基础上增加天数
                    expireTime = memberUser.getExpireTime().plusDays(days);
                } else {
                    // 如果会员已过期，从当前时间开始计算
                    expireTime = now.plusDays(days);
                }
                
                memberUser.setLevel(Math.max(memberUser.getLevel(), 1));  // 确保等级至少为1
                memberUser.setExpireTime(expireTime);
                memberUser.setUpdateTime(now);
                memberUserMapper.updateById(memberUser);
                log.info("用户会员信息更新成功: {}", memberUser);
            }
            
            // 解锁会员专享的文章
            try {
                // 检查是否有会员专享文章
                Integer memberArticleCount = jdbcTemplate.queryForObject(
                    "SELECT COUNT(*) FROM sys_article WHERE read_type = 2", Integer.class);
                log.info("系统中共有{}篇会员专享文章", memberArticleCount);
                
                if (memberArticleCount != null && memberArticleCount > 0) {
                    // 记录会员可访问的文章
                    String insertSql = "INSERT INTO member_article_access (user_id, article_id, expire_time, create_time) " +
                                      "SELECT ?, id, ?, NOW() FROM sys_article WHERE read_type = 2 " +
                                      "ON DUPLICATE KEY UPDATE expire_time = ?";
                    
                    int count = jdbcTemplate.update(insertSql, userId, memberUser.getExpireTime(), memberUser.getExpireTime());
                    log.info("已更新会员[{}]可访问的会员专享文章权限，记录数: {}，过期时间: {}", userId, count, memberUser.getExpireTime());
                    
                    // 验证会员访问权限是否正确设置
                    try {
                        Integer accessCount = jdbcTemplate.queryForObject(
                            "SELECT COUNT(*) FROM member_article_access WHERE user_id = ?", 
                            Integer.class, userId);
                        log.info("会员[{}]的文章访问权限记录数: {}", userId, accessCount);
                        
                        // 列出具体的会员文章
                        List<Map<String, Object>> memberArticles = jdbcTemplate.queryForList(
                            "SELECT id, title FROM sys_article WHERE read_type = 2 LIMIT 5");
                        log.info("会员文章示例: {}", memberArticles);
                    } catch (Exception e) {
                        log.error("查询会员文章访问权限记录失败", e);
                    }
                } else {
                    log.warn("系统中没有会员专享文章，不需要创建访问权限记录");
                }
            } catch (Exception e) {
                log.error("更新会员文章访问权限失败", e);
                // 不影响会员激活流程，所以捕获异常但继续执行
            }
            
            return true;
        } catch (Exception e) {
            log.error("激活会员失败", e);
            return false;
        }
    }

    /**
     * 重建所有会员的文章访问权限
     */
    public void rebuildAllMemberArticleAccess() {
        log.info("开始重建所有会员的文章访问权限...");
        try {
            // 检查是否有会员专享文章
            Integer memberArticleCount = jdbcTemplate.queryForObject(
                "SELECT COUNT(*) FROM sys_article WHERE read_type = 2", Integer.class);
            log.info("系统中共有{}篇会员专享文章", memberArticleCount);
            
            if (memberArticleCount == null || memberArticleCount == 0) {
                log.warn("系统中没有会员专享文章，不需要创建访问权限记录");
                return;
            }
            
            // 列出具体的会员文章
            List<Map<String, Object>> memberArticles = jdbcTemplate.queryForList(
                "SELECT id, title FROM sys_article WHERE read_type = 2");
            log.info("会员专享文章列表: {}", memberArticles);
            
            // 查询所有有效会员
            String memberSql = "SELECT user_id, expire_time FROM member_user WHERE expire_time > NOW()";
            List<Map<String, Object>> members = jdbcTemplate.queryForList(memberSql);
            
            log.info("找到{}个有效会员", members.size());
            
            if (members.isEmpty()) {
                log.warn("系统中没有有效会员，不需要创建访问权限记录");
                return;
            }
            
            // 清空旧的访问权限记录
            jdbcTemplate.update("TRUNCATE TABLE member_article_access");
            log.info("已清空旧的会员文章访问权限记录");
            
            // 批量插入新的访问权限记录
            StringBuilder sql = new StringBuilder();
            sql.append("INSERT INTO member_article_access (user_id, article_id, expire_time, create_time) ");
            sql.append("SELECT u.user_id, a.id, u.expire_time, NOW() ");
            sql.append("FROM member_user u CROSS JOIN sys_article a ");
            sql.append("WHERE u.expire_time > NOW() AND a.read_type = 2");
            
            int count = jdbcTemplate.update(sql.toString());
            log.info("已为所有会员重新创建文章访问权限记录，共{}条", count);
            
            // 再次验证写入的记录
            Integer accessCount = jdbcTemplate.queryForObject(
                "SELECT COUNT(*) FROM member_article_access", Integer.class);
            log.info("会员文章访问权限记录数: {}", accessCount);
            
            // 验证特定用户的访问权限 (可选，若需特别关注某用户)
            for (Map<String, Object> member : members) {
                Long userId = ((Number) member.get("user_id")).longValue();
                Integer userAccessCount = jdbcTemplate.queryForObject(
                    "SELECT COUNT(*) FROM member_article_access WHERE user_id = ?", 
                    Integer.class, userId);
                log.info("会员[{}]的文章访问权限记录数: {}", userId, userAccessCount);
            }
            
        } catch (Exception e) {
            log.error("重建会员文章访问权限失败", e);
        }
    }
} 